﻿//=============================================================================
// Date		: March 11, 2010
//	Author	: Anthony Paul Ortiz
//	License	: CPOL
//=============================================================================

#region Using Statements

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Threading;
using System.Windows.Threading;

#endregion Using Statements

namespace WpfAdvControls.Plate
{
    public class MTObservableCollection<T> : ObservableCollection<T>
    {
        private readonly Dictionary<NotifyCollectionChangedEventHandler, CollectionChangedWrapperEventData>
            collectionChangedHandlers;

        #region Constructors

        public MTObservableCollection()
        {
            collectionChangedHandlers =
                new Dictionary<NotifyCollectionChangedEventHandler, CollectionChangedWrapperEventData>();
        }

        #endregion Constructors

        #region Handlers

        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            var handlers =
                collectionChangedHandlers.ToArray();

            if (handlers.Length > 0)
            {
                foreach (var kvp in handlers)
                {
                    if (kvp.Value.Dispatcher == null)
                    {
                        kvp.Value.Action(e);
                    }
                    else
                    {
                        kvp.Value.Dispatcher.Invoke(kvp.Value.Action, DispatcherPriority.DataBind, e);
                    }
                }
            }
        }

        #endregion Handlers

        public override event NotifyCollectionChangedEventHandler CollectionChanged
        {
            add
            {
                //Dispatcher dispatcher = Dispatcher.CurrentDispatcher; // should always work
                var dispatcher = Dispatcher.FromThread(Thread.CurrentThread);
                // experimental (can return null)...
                collectionChangedHandlers.Add(value,
                    new CollectionChangedWrapperEventData(dispatcher,
                        args => value(this, args)));
            }
            remove { collectionChangedHandlers.Remove(value); }
        }
    }
}